package com.gfxy.modules.items.service.impl;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gfxy.modules.common.entity.MemberList;
import com.gfxy.modules.common.service.IMemberListService;
import com.gfxy.modules.excel.ExcelUtil;
import com.gfxy.modules.items.entity.GfxyBaseBean;
import com.gfxy.modules.items.entity.teachingresult.TeachingResult;
import com.gfxy.modules.items.entity.teachingresult.TeachingResultContent;
import com.gfxy.modules.items.service.DictTranslater;
import com.gfxy.modules.items.service.IProjectGfxyService;
import com.gfxy.modules.system.service.ISysDepartService;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.ImportExcelUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author: lijixin 2021/10/29 5:38 下午
 */
public abstract class AbstractProjectServiceImpl<M extends BaseMapper<T>,T extends GfxyBaseBean> extends ServiceImpl<M,T> implements IProjectGfxyService<T> {


    @Autowired
    protected IMemberListService memberListService;
    @Autowired
    protected CommonAPI commonAPI;
    @Autowired
    protected DictTranslater dictTranslater;
    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private ISysDepartService iSysDepartService;


    protected int IS_CUSTOM = 0;

    protected int START_ROW_NUM = 1;

    protected String memberNameSeparator = "、";

    protected int memberCellNum = 0;




    @Override
    @Transactional(rollbackFor=Exception.class)
    public void saveMain(T t, List<MemberList> memberLists) {
        this.baseMapper.insert(t);
        this.setSomePropertyToMemberList(t,memberLists);
        memberListService.saveList(t.getId(),memberLists);
    }

    @Override
    @Transactional(rollbackFor=Exception.class)
    public void updateMain(T t,List<MemberList> memberLists) {
        t.setIsPass(0);
        this.baseMapper.updateById(t);
        //1.先删除子表数据
        memberListService.deleteByItemId(t.getId());
        this.setSomePropertyToMemberList(t,memberLists);
        memberListService.saveList(t.getId(),memberLists);
    }

    @Override
    @Transactional(rollbackFor=Exception.class)
    public void delMain(String id) {

        memberListService.deleteByItemId(id);
        this.baseMapper.deleteById(id);

    }

    @Override
    @Transactional(rollbackFor=Exception.class)
    public void delBatchMain(Collection<? extends Serializable> idList) {
        idList.forEach((id)-> delMain(id.toString())
        );
    }

    @Override
    public void passBatch(Collection<? extends Serializable> idList, String isPass) {
        for(Serializable id:idList) {
            this.pass(id.toString(), isPass);
        }
    }


    protected  void pass(String id, String isPass){};

    protected abstract T getOneProject(Row row) ;


    protected  String[] getMemberArray(Row row){
        String nameStrs = ExcelUtil.formatCell(row.getCell(memberCellNum));
        return nameStrs.split(memberNameSeparator);
    }

    protected List<MemberList> getMemberList(Row row, T t, ExcelResult excelResult){
        String[] memberArray = this.getMemberArray(row);
        List<MemberList> memberListList = new ArrayList<>();
        for (int j = 0; j < memberArray.length; j++) {
            String memberStr = memberArray[j];
            List<MemberList> memberLists = memberListService.selectByRealName(memberStr.trim());
            if (memberLists.size() == 1) {
                MemberList memberList = memberLists.get(0);
                memberList.setRanked(j + 1);
                memberList.setItemValue(t.getItemValue());
                memberList.setIsCustom(IS_CUSTOM);

                memberListList.add(memberList);
            } else if (memberLists.size() == 0) {
                excelResult.setSuccess(false);
                excelResult.setErrorMsg( t.getProjectName() + "中，教师:" + memberStr + " 数据不存在，已替换成”校外人员“; ");


                List<MemberList> memberListsOther = memberListService.selectByRealName("校外人员");
                MemberList memberList = memberListsOther.get(0);
                memberList.setRanked(j + 1);
                memberList.setItemValue(t.getItemValue());
                memberList.setIsCustom(IS_CUSTOM);

                memberListList.add(memberList);
            } else if (memberLists.size() > 1) {
                excelResult.setSuccess(false);
                excelResult.setErrorMsg( t.getProjectName() + "中，教师:" + memberStr + " 存在同名教师，请手动处理; ");
                MemberList memberList = new MemberList();
                memberList.setRanked(j + 1);
                memberList.setItemValue(t.getItemValue());
                memberList.setIsCustom(IS_CUSTOM);

                memberListList.add(memberList);
            }

        }
        return memberListList;
    }


    @Override
    public Result<?> importExcel(MultipartFile file) throws IOException {
        int SHEET_NUM = 0;
        int errorLines = 0;
        int successLines = 0;
        InputStream inputStream = file.getInputStream();
        if (!(inputStream).markSupported()) {
            inputStream = new PushbackInputStream(inputStream, 8);
        }
        Workbook book = WorkbookFactory.create(inputStream);
        Sheet sheet = book.getSheetAt(SHEET_NUM);
        List<String> errorMessage = new ArrayList<>();

        for (int i = START_ROW_NUM; i <= sheet.getLastRowNum(); i++) {
            ExcelResult excelResult = new ExcelResult(true,"");
            try{

                Row row = sheet.getRow(i);
                T t = this.getOneProject(row);

                List<MemberList> memberListList = this.getMemberList(row, t, excelResult);

                Double[] memberListScore = this.getMemberListScore(t.getTotalScore(), memberListList.size());
                for (int j = 0; j < memberListList.size(); j++) {
                    memberListList.get(j).setScore(memberListScore[j]);
                }
                this.saveMain(t,memberListList);

            } catch ( Exception e){
                e.printStackTrace();
                log.error(e.getMessage(),e);
                excelResult.setErrorMsg("excel 第 " + i+ "行数据解析出现位置异常; ");
            }

            if(excelResult.isSuccess()){
                successLines++;
            } else {
                errorLines++;
                errorMessage.add(excelResult.getErrorMsg());
            }

        }

        return ImportExcelUtil.imporReturnRes(errorLines, successLines, errorMessage);
    }


    private void setSomePropertyToMemberList(T t, List<MemberList> memberLists){
        for (MemberList memberList : memberLists) {
            memberList.setItemId(t.getId());
            memberList.setDate(t.getDate());
            memberList.setItemValue(t.getItemValue());
        }
    }

    @Override
    public Double[] getMemberListScore(double totalScore, int memberNum) {

        Double[] result = new Double[memberNum];
        if (memberNum == 1) {
            result[0] = totalScore;
        } else {
            double otherScore = 0.0;
            for (int i = 1; i < result.length; i++) {
                double tempProportion = this.computeProportion(i + 1, memberNum);
                double tempScore = totalScore * tempProportion;
                BigDecimal bg = new BigDecimal(tempScore);
                tempScore = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                result[i] = tempScore;
                otherScore = otherScore + tempScore;
            }
            double result0 = totalScore - otherScore;
            BigDecimal bg = new BigDecimal(result0);
            result0 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            result[0] = result0;
        }
        return result;
    }

    /**
     * 重写此方法
     * @param ranked 第几名
     * @param totalNum  共几人
     * @return
     */
    protected double computeProportion(int ranked, int totalNum){

        if(totalNum==1){
            return 1.0;
        } else if(totalNum == 2){
            if(ranked ==1){
                return 0.6;
            } else if(ranked == 2){
                return 0.4;
            } else {
                return 0.0;
            }
        } else if(totalNum == 3){
            if(ranked ==1){
                return 0.5;
            } else if(ranked == 2){
                return 0.3;
            } else if(ranked == 3){
                return 0.2;
            } else {
                return 0.0;
            }
        } else if(totalNum == 4){
            if(ranked ==1){
                return 0.5;
            } else if(ranked == 2){
                return 0.25;
            } else if(ranked == 3){
                return 0.15;
            } else if(ranked == 4){
                return 0.1;
            } else {
                return 0.0;
            }
        } else if(totalNum == 5){
            if(ranked ==1){
                return 0.45;
            } else if(ranked == 2){
                return 0.2;
            } else if(ranked == 3){
                return 0.15;
            } else if(ranked == 4){
                return 0.1;
            } else if(ranked == 5){
                return 0.1;
            } else {
                return 0.0;
            }
        } else if(totalNum == 6){
            if(ranked ==1){
                return 0.45;
            } else if(ranked == 2){
                return 0.2;
            } else if(ranked == 3){
                return 0.15;
            } else if(ranked == 4){
                return 0.1;
            } else if(ranked == 5){
                return 0.05;
            } else if(ranked == 6){
                return 0.05;
            }else {
                return 0.0;
            }
        } else if(totalNum >=7){
            if(ranked == 1){
                return 0.5;
            } else if(ranked > 1){
                return Math.floor(0.5*10000/(totalNum-1))/10000.0 ;
            } else {
                return 0.0;
            }
        } else {
            return 0.0;
        }
    }

    public TeachingResult getTeachingResultContent(MemberList memberList)  {

        String itemId = memberList.getItemId();

        T t = this.getById(itemId);

        List<MemberList> memberLists = this.memberListService.selectByItemId(String.valueOf(itemId));
        String title = commonAPI.translateDict("TEACHING_BUILDING_TYPE",String.valueOf(memberList.getItemValue()));

        String projectName = t.getProjectName();

        List<TeachingResultContent> contents = this.createTeachingResultContent(t);

        TeachingResult result = new TeachingResult();
        int projectType =  memberList.getItemValue();

        if(projectType == 3001 || projectType == 3002){
            TeachingResultContent teachingResultContent1 = new TeachingResultContent();
            teachingResultContent1.setType(2);
            teachingResultContent1.setKey("负责人");

            LoginUser user = sysBaseAPI.getUserByName(memberLists.get(0).getTeacherId());
            teachingResultContent1.setValue(user.getRealname());

            TeachingResultContent teachingResultContent2 = new TeachingResultContent();
            teachingResultContent2.setType(2);
            teachingResultContent2.setKey("排名");
            teachingResultContent2.setValue(memberList.getRanked() + "/" + memberLists.size());


            TeachingResultContent teachingResultContent4 = new TeachingResultContent();
            teachingResultContent4.setType(2);
            teachingResultContent4.setKey("积分部门");
            teachingResultContent4.setValue(iSysDepartService.queryDepartByOrgCode(memberList.getOrgId()).getDepartName());

            TeachingResultContent teachingResultContent3 = new TeachingResultContent();
            teachingResultContent3.setType(2);
            teachingResultContent3.setKey("积分");
            teachingResultContent3.setValue(String.valueOf(memberList.getScore()));

            contents.add(teachingResultContent1);
            contents.add(teachingResultContent2);
            contents.add(teachingResultContent4);
            contents.add(teachingResultContent3);

            result.setTitle(title);
            result.setProjectName(projectName);
            result.setContents(contents);
            result.setRecord(t);
        } else
        if(projectType == 6 || projectType == 9 || projectType == 26 || projectType==27){

            TeachingResultContent teachingResultContent3 = new TeachingResultContent();
            teachingResultContent3.setType(2);
            teachingResultContent3.setKey("积分");
            teachingResultContent3.setValue(String.valueOf(memberList.getScore()));
            teachingResultContent3.setLevel(1);
            contents.add(teachingResultContent3);

            result.setTitle(title);
            result.setProjectName(projectName);
            result.setContents(contents);
            result.setRecord(t);

        } else {
            TeachingResultContent teachingResultContent1 = new TeachingResultContent();
            teachingResultContent1.setType(2);
            teachingResultContent1.setKey("负责人");

            LoginUser user = sysBaseAPI.getUserByName(memberLists.get(0).getTeacherId());
            teachingResultContent1.setValue(user.getRealname());

            TeachingResultContent teachingResultContent2 = new TeachingResultContent();
            teachingResultContent2.setType(2);
            teachingResultContent2.setKey("排名");
            teachingResultContent2.setValue(memberList.getRanked() + "/" + memberLists.size());

            TeachingResultContent teachingResultContent3 = new TeachingResultContent();
            teachingResultContent3.setType(2);
            teachingResultContent3.setKey("积分");
            teachingResultContent3.setValue(String.valueOf(memberList.getScore()));

            contents.add(teachingResultContent1);
            contents.add(teachingResultContent2);
            contents.add(teachingResultContent3);

            result.setTitle(title);
            result.setProjectName(projectName);
            result.setContents(contents);
            result.setRecord(t);
        }


        return result;
    }

    protected List<TeachingResultContent> createTeachingResultContent(T t) {
        List<TeachingResultContent> teachingResultContents = new ArrayList<>();
        return teachingResultContents;
    }

    public static class ExcelResult{
        private boolean isSuccess ;
        private String errorMsg;

        public boolean isSuccess() {
            return isSuccess;
        }

        public void setSuccess(boolean success) {
            isSuccess = success;
        }

        public String getErrorMsg() {
            return errorMsg;
        }

        public void setErrorMsg(String errorMsg) {
            this.errorMsg = this.errorMsg + errorMsg;
        }

        public ExcelResult(boolean isSuccess, String errorMsg) {
            this.isSuccess = isSuccess;
            this.errorMsg = errorMsg;
        }
    }
}
